﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;
using System.Diagnostics;
using Api;
using System.IO;
using Api.util;
using OcmKeep.entity;
using System.Xml;
using ys000;
using Newtonsoft.Json.Linq;
using ArcsoftFaceTest;
using System.Configuration;

namespace OcmKeep
{ 
    public partial class Form1 : Form
    {
        int[] InMachinesDevNo = new int[] { 0x1, 0x3, 0x5, 0x7, 0x9 };
        int[] OutMachinesDevNo = new int[] { 0x2, 0x4, 0x6, 0x8, 0xa };
        //int[] InMachinesDevNo = new int[] { 0x11, 0x13, 0x15, 0x17 };
        //int[] OutMachinesDevNo = new int[] { 0x12, 0x14, 0x16, 0x18 };

        private static Mutex mutexFace = new Mutex();  
        int TOTALNUM = 50;    //接受数据长度
        int DEVNUM = 4; //设备数
        private string[] devh = null;//new string[DEVNUM];
        byte[] devno = null;//new byte[DEVNUM];
        byte[] devResult;
        bool running = false;
        DataHelper dh = new DataHelper();
        byte[] fingerTemp = new byte[512];
        int[] InMachines = null;//{1,2};
        int[] OutMachines = null;//{3,4};
        int[] BusyMachine = null;//闸机通道忙
        bool[] Conflicting = null;
        int currentMachineIndex = 0;
        object InSwiperLock = new object();
        object OutSwiperLock = new object();
        object ClearConflictLock = new object();
        object SetConflictLock = new object();
        object CheckLock = new object();
        object FaceLock = new object();
        long CLoseTime = 0L;
        long closespace = 3 * 1000 * 10000;
        bool comchecking = false;
        static bool LogFlag = false;
        int sendspace = 20;
        int packlen = 0;
        IniHelper ini;
        string historycom = "";
        Dictionary<string, string> OldOpenDic = new Dictionary<string, string>(2);
        string[] DoorList = null;
        List<ManualBox> ManualBoxList = new List<ManualBox>();
        List<TextBox> ManualTextList = new List<TextBox>();
        bool EditName = false;
        bool FaceModel = false;

        bool iscaptrue = false;
        public static List<PictureBox> hostPb = new List<PictureBox>();
        List<string> hostCarmera = new List<string>();
        public List<PictureBox> picboxs = new List<PictureBox>();//创建对象数组，存放picbox对象，最多9画面，所以最多9个
        public List<IntPtr> handle = new List<IntPtr>();//存放播放句柄
        public List<string> cameraId = new List<string>();//存放cameraid
        public List<IntPtr> SessionId = new List<IntPtr>();//存放申请的session
        int faceErrorNum = 0;

        #region 海景人脸
        //IntPtr faceComp = new IntPtr();
        //HJFaceModel[] hjface = new HJFaceModel[5];
        #endregion
        int FACETHREADNUM = 12;
        string pathautoCapT = @"C:/face";
        List<byte[]> featrueList1 = new List<byte[]>();
        List<byte[]> featrueList2 = new List<byte[]>();
        AmFaceVerify amface = new AmFaceVerify();//虹软人脸 比对
        AmFaceVerify amface1 = new AmFaceVerify();//虹软人脸 特征采集
        //AmFaceVerify amface2 = new AmFaceVerify();//虹软人脸 比对
        //AmFaceVerify amface3 = new AmFaceVerify();//虹软人脸 特征采集
        string cameraNames = ConfigurationManager.AppSettings["CameraNames"].ToString();
        string FaceScore = ConfigurationManager.AppSettings["Score"].ToString();
        
        long faceOverTime = 5000 * 10000;
        public class PAR
        {
            public int delay { set; get; }
            public int addr { set; get; }
        }
        private class FacePar {
            public int addr{set;get;}
            public int index { set; get; }
            public string filename { set; get; }
            public AmFaceVerify amface { set; get; }
        }
        Dictionary<string, BrackeMachine> bm_Dev = new Dictionary<string, BrackeMachine>();
        Dictionary<string, StateBox> stateList = new Dictionary<string, StateBox>();
        Stopwatch DelaySw = new Stopwatch();//串口发送指令计时器
        List<Stopwatch> lockswlist = null;
        int[] UseMachines = null;
        //UI
        Point mouseOff; bool canMove = false;
        Color HeaderBack = Color.FromArgb(50, 50, 50);
        Color ForeColor = Color.FromArgb(160, 160, 160);
        Color StateError = Color.FromArgb(222, 83, 71);//错误
        Color StateBusy = Color.FromArgb(255, 205, 68);//发送指紋
        Color StateWait = Color.FromArgb(255,153,0);//比对指纹
        Color StateOff = Color.FromArgb(30, 30, 30);//无通信
        Color StateOn = Color.FromArgb(31, 164, 99);//正常
        Color StateSql = Color.FromArgb(22,136,250);//sql错误
        Color StateFace = Color.FromArgb(104, 33, 122);//人脸照片加载错误

        StateBox cuStateBox = null;
        int curAddr = -1;
        delegate void InvokeCall(object msg);
        private delegate void ChildThreadExceptionHandler(Exception ex);
        private event ChildThreadExceptionHandler ChildThreadException;
        bool faceinitRes = false;
        bool capRes = false;
        public Form1()
        {
            InitializeComponent(); 
        }
        #region FormLoad
        private void Form1_Load(object sender, EventArgs e)
        {
            btnStart.MouseEnter += button1_MouseEnter;
            btnStart.MouseLeave += button1_MouseLeave;
            this.Resize += Form1_Resize;
            this.FormClosing += Form1_FormClosing;
            header.MouseDown += Form1_MouseDown;
            header.MouseUp += Form1_MouseUp;
            header.MouseMove += Form1_MouseMove;
            header.BackColor = btnStart.BackColor = HeaderBack;
            btnStart.ForeColor = ForeColor;
            close.MouseEnter += close_MouseEnter;
            close.MouseLeave += close_MouseLeave;
            option.MouseEnter += option_MouseEnter;
            option.MouseLeave += option_MouseLeave;
            mini.MouseEnter += mini_MouseEnter;
            mini.MouseLeave += mini_MouseLeave;
            notifyIcon.MouseClick += notifyIcon_MouseClick;
            comboBoxPortSelect.KeyPress += comboBoxPortSelect_KeyPress;
            CheckForIllegalCrossThreadCalls = false;
            InitParam();
            InitCom();
            //LogClearThread();
            //button1_Click(this, null);//点击开始按钮
        }

        void comboBoxPortSelect_KeyPress(object sender, KeyPressEventArgs e)
        {
            e.Handled = true;
        }
        #endregion
        #region 初始化配置
        private void InitParam()
        {
            // 写入ini
            string Current = AppDomain.CurrentDomain.BaseDirectory;//获取当前根目录
            ini = new IniHelper(Current + "/Config/config.ini");
            string _sendspace = ini.ReadValue("Setting", "sendspace");
            string _logflag = ini.ReadValue("Setting", "logflag");
            string _passway = ini.ReadValue("Setting", "passway");//通道数
            string InMachineAddr = ini.ReadValue("Setting", "inaddr");
            string OutMachineAddr = ini.ReadValue("Setting", "outaddr");
            string face = ini.ReadValue("Setting","face");
            if (face!=null&&face=="1")
            {
                FaceModel = true;
                cameraPanel.Visible = true;
            }
            int devnum = 2; 
            int.TryParse(_passway,out devnum);
            if (devnum < 1)
            {
                ini.WriteValue("Setting", "passway", devnum.ToString());
                devnum = 2;
            }
            //串口号索引
            historycom = ini.ReadValue("Setting", "com");
            string DoorNames = ini.ReadValue("Setting", "doorname");
            if (_passway == null || _passway.CompareTo("0") <= 0) _passway = "2";
            if (!int.TryParse(_sendspace, out sendspace))
            {
                sendspace = 20;//发送间隔
                ini.WriteValue("Setting", "sendspace", sendspace.ToString());
            }
            if (DoorNames == null || DoorNames.Length < 3) {
                DoorNames = getDoorName(devnum);
                ini.WriteValue("Setting", "doorname", DoorNames);
            }
            if (InMachineAddr == null || InMachineAddr.Trim().Length < 7)
            {
                ini.WriteValue("Setting", "inaddr", "1,3,5,7");
            }
            else
            {
                DataTrans.strToByte(InMachineAddr, ref InMachinesDevNo);
            }
            if (OutMachineAddr == null || OutMachineAddr.Trim().Length < 7)
            {
                ini.WriteValue("Setting", "outaddr", "2,4,6,8");
            }
            else
            {
                DataTrans.strToByte(OutMachineAddr, ref OutMachinesDevNo);
            }
            if (_logflag == "1") LogFlag = true;//运行日志
            else LogFlag = false;
            InitMachines(_passway,DoorNames);
            AutoRun.runWhenStart(true, "闸机控制", Current + @"\闸机控制.exe");
        }
        #endregion 

        #region 闸机别名
        private string getDoorName(int devnum)
        {
            string res ="";
            for (int i = 0; i < devnum; ++i)
            {
                res += "," + InMachinesDevNo[i];
                res += "," + OutMachinesDevNo[i];
            }
            return res.Substring(1);
        }
        #endregion

        #region 闸机地址初始化
        //闸机地址初始化
        public void InitMachines(string passway,string DoorNames)
        {
            switch (passway)
            {
                case "1":
                    DEVNUM = 2;
                    InMachines = new int[] { InMachinesDevNo[0] };
                    OutMachines = new int[] { OutMachinesDevNo[0] };
                    UseMachines = new int[] { InMachinesDevNo[0], OutMachinesDevNo[0] };
                    BusyMachine = new int[] { -1 };
                    Conflicting = new bool[] { false };
                    break;
                case "2":
                    DEVNUM = 4;
                    InMachines = new int[] { InMachinesDevNo[0], InMachinesDevNo[1] };
                    OutMachines = new int[] { OutMachinesDevNo[0], OutMachinesDevNo[1] };
                    UseMachines = new int[] { InMachinesDevNo[0], OutMachinesDevNo[0],
                    InMachinesDevNo[1], OutMachinesDevNo[1]};
                    BusyMachine = new int[] { -1, -1 };
                    Conflicting = new bool[] { false, false };
                    break;
                case "3":
                    DEVNUM = 6;
                    InMachines = new int[] { InMachinesDevNo[0], InMachinesDevNo[1], InMachinesDevNo[2] };
                    OutMachines = new int[] { OutMachinesDevNo[0], OutMachinesDevNo[1], OutMachinesDevNo[2] };
                    UseMachines = new int[] { InMachinesDevNo[0], OutMachinesDevNo[0],
                    InMachinesDevNo[1], OutMachinesDevNo[1],InMachinesDevNo[2], OutMachinesDevNo[2]};
                    BusyMachine = new int[] { -1, -1, -1 };
                    Conflicting = new bool[] { false, false, false };
                    break;
                case "4":
                    DEVNUM = 8;
                    InMachines = new int[] { InMachinesDevNo[0], InMachinesDevNo[1], InMachinesDevNo[2], InMachinesDevNo[3] };
                    OutMachines = new int[] { OutMachinesDevNo[0], OutMachinesDevNo[1], OutMachinesDevNo[2], OutMachinesDevNo[3] };
                    UseMachines = new int[] { InMachinesDevNo[0], OutMachinesDevNo[0],
                    InMachinesDevNo[1], OutMachinesDevNo[1],InMachinesDevNo[2], OutMachinesDevNo[2],InMachinesDevNo[3], OutMachinesDevNo[3]};
                    BusyMachine = new int[] { -1, -1, -1, -1 };
                    Conflicting = new bool[] { false, false, false, false };
                    break;
                case "5":
                    DEVNUM = 10;
                    InMachines = new int[] { InMachinesDevNo[0], InMachinesDevNo[1], InMachinesDevNo[2], InMachinesDevNo[3], InMachinesDevNo[4] };
                    OutMachines = new int[] { OutMachinesDevNo[0], OutMachinesDevNo[1], OutMachinesDevNo[2], OutMachinesDevNo[3], OutMachinesDevNo[4] };
                    UseMachines = new int[] { InMachinesDevNo[0], OutMachinesDevNo[0],
                    InMachinesDevNo[1], OutMachinesDevNo[1],InMachinesDevNo[2], OutMachinesDevNo[2],InMachinesDevNo[3], OutMachinesDevNo[3],InMachinesDevNo[4], OutMachinesDevNo[4]};
                    BusyMachine = new int[] { -1, -1, -1, -1, -1 };
                    Conflicting = new bool[] { false, false, false, false, false };
                    break;
                default:
                    DEVNUM = 4;
                    InMachines = new int[] { InMachinesDevNo[0], InMachinesDevNo[1] };
                    OutMachines = new int[] { OutMachinesDevNo[0], OutMachinesDevNo[1] };
                    UseMachines = new int[] { InMachinesDevNo[0], OutMachinesDevNo[0],
                    InMachinesDevNo[1], OutMachinesDevNo[1]};
                    BusyMachine = new int[] { -1, -1 };
                    Conflicting = new bool[] { false, false };
                    break;
            }
            devh = new string[DEVNUM];
            devno = new byte[DEVNUM];
            lockswlist = new List<Stopwatch>();
            bm_Dev.Clear();
            try
            {
                DoorList = DoorNames.Split(',');
            }
            catch { 

            }
            
            for (int i = 0, len = InMachines.Length; i < len; ++i)
            {
                stateList.Add(InMachines[i] + "", addstatebox(InMachines[i]));
                stateList.Add(OutMachines[i] + "", addstatebox(OutMachines[i]));
                addManualBox(InMachines[i],true);
                addManualBox(OutMachines[i], false);
            }
            for (int i = 0, len = DEVNUM / 2; i < len; ++i) lockswlist.Add(new Stopwatch());
            
        }
        #endregion

        #region 状态条
        private StateBox addstatebox(int index)
        {
            StateBox p = new StateBox(20);
            p.addr = index.ToString();
            //p.Click += p_Click;
            p.Height = 12;
            p.BackColor = StateOff;
            stateBox.Controls.Add(p);
            int y = 0;
            int x = currentMachineIndex;
            if (currentMachineIndex % 2 != 0)
            {
                y = 17; x = currentMachineIndex - 1;
            }
            currentMachineIndex++;
            p.Location = new Point(x * 15, y);
            p.Cursor = Cursors.Hand;
            BrackeMachine bm = new BrackeMachine();
            bm.DevNo = index;
            bm.Package = dh.GetPackage(index, "", DataHelper.CMD.CMD_ASK, ref packlen);
            bm_Dev.Add(index.ToString(), bm);
            return p;
        }
        #endregion
        void p_Click(object sender, EventArgs e)
        {
            StateBox p = sender as StateBox;
            if (p != null)
            {
                if (cuStateBox != null)
                {
                    cuStateBox.TextColor = Color.White;
                }
                cuStateBox = p;
                p.TextColor = StateError;
                int.TryParse(p.addr, out curAddr);
            }
        }

        #region 初始化人脸识别
        private void InitFace() {
            try
            {
                if (!Directory.Exists(pathautoCapT))
                {
                    Directory.CreateDirectory(pathautoCapT);
                }
                bool ret = false;
                bool ret1 = false;
                DebugLog(String.Format("人脸比对初始化：{0}", ret = amface.AFD_Init()));
                DebugLog(String.Format("人脸检测初始化：{0}", ret1 = amface1.AFD_Init()));
                //DebugLog(String.Format("人脸检测初始化：{0}", ret1 = amface2.AFD_Init()));
                //DebugLog(String.Format("人脸检测初始化：{0}", ret1 = amface3.AFD_Init()));
                faceinitRes = ret;
                //new Thread(new ThreadStart(InitCamera)).Start();
                InitCamera();
            }
            catch (Exception e) {
                DebugLog(e.StackTrace);
            }
        }
        #endregion



        #region 初始化相机
        private void InitCamera() {
            HkAction.MainForm = this;
            try
            {
                HkAction.Start();//进入系统自动初始化库    turn;
                if (HkAction.GetAccessToken() != null)
                {
                    jsonHandle(HkAction.playList());
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("异常！" + ex.ToString(), "提示", MessageBoxButtons.OK);
            }
        }
        public void jsonHandle(string str)
        {
            string jsonStr = str;
            JObject jsonObj = JObject.Parse(jsonStr);
            JArray jar = JArray.Parse(jsonObj["cameraList"].ToString());
            int carmeraCount = Int32.Parse(jsonObj["count"].ToString());
            List<string> deviceNames = new List<string>();
            DebugLog(str);
            if(faceinitRes){
                string[] name = cameraNames.Split(',');
                for (int m = 0; m < carmeraCount; m++)
                {
                    JObject j = JObject.Parse(jar[m].ToString());//取第几个摄像头信息放入对象j
                    string deviceName = j["deviceName"].ToString();
                    string isEncrypt = j["isEncrypt"].ToString();//取出摄像头状态
                    Console.WriteLine();
                    //if (isEncrypt == "1")
                    //{
                    //    //cameraState.Text = "已加密";//把摄像头加密状态给label
                    //}
                    string status = j["status"].ToString();
                    Label label3 = new Label();
                    if (status != "0"){
                        cameraState.Text = "已在线";
                        PictureBox picbox = new PictureBox();
                        deviceNames.Add(deviceName);
                        picboxs.Add(picbox);
                        cameraId.Add(j["cameraId"].ToString());
                    }
                }
                for (int n = 0; n < name.Length; ++n)
                { 
                    for(int d=0;d<deviceNames.Count;++d){
                        if(deviceNames[d].Equals(name[n]))
                        {
                            hostCarmera.Add(cameraId[d]);
                            hostPb.Add(picboxs[d]);
                        }
                    }
                }
            }
            else
            {
                MessageBox.Show("人脸模块初始化失败", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
            } 
            
            if (!Play())
            {
                MessageBox.Show("摄像头初始化失败", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else Start();
            btnStart.Enabled = true;
        }

        private bool Play() {
            int num = hostCarmera.Count;
            int erroNum = 0;
            for (int n = 0; n < num; ++n)
            {
                SessionId.Add(HkAction.AllocSession());
                if (!PlayVideo(hostPb[n].Handle, hostCarmera[n], SessionId[n])) erroNum++;
            }
            if (erroNum == num) return false;
            return true;
        }

        private bool PlayVideo(IntPtr handle, string cameraid,IntPtr sessionId)
        {
            bool ret = HkAction.Play(handle, cameraid, sessionId);
            string a = "播放" + (ret ? "成功" : "失败");
            Console.WriteLine(a);
            DebugLog(a);
            if (ret) {
                iscaptrue = true;
            }
            return ret;
        }
        long errorTime = 0;
        bool facerestarting = false;
        //private void autoCapT1()
        //{
        //    long t = DateTime.Now.Ticks;
        //    int pathIdx1 = 1;
        //    bool ret = false;
        //    string path = pathautoCapT;
        //    while (iscaptrue)
        //    {
        //        try
        //        {
        //            //t = DateTime.Now.Ticks;
        //            t = DateTime.Now.Ticks;
        //            path = CapOne(ref pathIdx1, pathautoCapT, ref ret);
        //            //path = @"C:\face\face1.jpg";
        //            if (facerestarting || !ret) continue;
        //            //Console.WriteLine("拍照1:{0}", (DateTime.Now.Ticks - t) / 10000);
        //            byte[] tmp1 = amface1.detectFace(path);
        //            //Console.WriteLine("获取特征1：{0}", (DateTime.Now.Ticks - t) / 10000);
        //            if (tmp1 != null)
        //            {
        //                Thread.Sleep(30);
        //                if (featrueList1.Count >= FACETHREADNUM) featrueList1.RemoveAt(0);
        //                featrueList1.Add(tmp1);
        //                //updateTxt(String.Format("获取特征值,总数{0}", featrueList1.Count));
        //            }
        //        }
        //        catch (Exception e)
        //        {
        //            faceErrorNum++;
        //            if (errorTime == 0) errorTime = DateTime.Now.Ticks;
        //            if (DateTime.Now.Ticks - errorTime < faceOverTime)
        //            {
        //                if (faceErrorNum >= 10)
        //                {
        //                    updateTxt("重启人脸引擎");
        //                    DebugLog("重启人脸引擎");
        //                    if (facerestarting)
        //                    {
        //                        updateTxt("人脸引擎重启中...");
        //                        return;
        //                    }
        //                    new Thread(new ThreadStart(restartAFD)).Start();
        //                    updateTxt("重启人脸引擎");
        //                }
        //            }
        //            else {
        //                errorTime = 0;
        //            }
        //            Console.WriteLine(e.StackTrace);
        //        }
        //    }
        //    DebugLog("拍照线程1退出");
        //}
        //private void autoCapT2()
        //{

        //    long t = DateTime.Now.Ticks;
        //    int pathIdx2 = 6;
        //    string path2;
        //    bool ret = false;
        //    while (iscaptrue)
        //    {

        //        try
        //        {
        //            //t = DateTime.Now.Ticks;
        //            path2 = CapTwo(ref pathIdx2, pathautoCapT, ref ret);
        //            if (facerestarting || !ret) continue;
                    
        //            byte[] tmp2 = amface3.detectFace(path2);
        //            //Console.WriteLine("获取特征2：{0}", (DateTime.Now.Ticks - t) / 10000);
        //            if (tmp2 != null)
        //            {
        //                Thread.Sleep(30);
        //                if (featrueList2.Count >= 6) featrueList2.RemoveAt(0);
        //                featrueList2.Add(tmp2);
        //                updateTxt(String.Format("featrueList2获取特征值,总数{0}", featrueList2.Count));
        //            }

        //        }
        //        catch (Exception e)
        //        {

        //            DebugLog("重启人脸引擎"+e.StackTrace);
        //            faceErrorNum++;
        //            if (errorTime == 0) errorTime = DateTime.Now.Ticks;
        //            if (DateTime.Now.Ticks - errorTime < faceOverTime)
        //            {
        //                if (faceErrorNum >= 10)
        //                {
        //                    if (facerestarting)
        //                    {
        //                        updateTxt("人脸引擎重启中...");
        //                        return;
        //                    }
        //                    new Thread(new ThreadStart(restartAFD)).Start();
        //                    updateTxt("重启人脸引擎");
        //                }
        //            }
        //            else
        //            {
        //                errorTime = 0;
        //            }
        //            Console.WriteLine(e.StackTrace);
        //        }
        //    }
        //    DebugLog("拍照线程2退出");
        //}

        private void restartAFD() {
            facerestarting = true;
            try
            {
                amface.Uninit();
                amface1.Uninit();
                //amface2.Uninit();
                ////amface3.Uninit();
                bool amret1 = amface.AFD_Init();
                bool amret2 = amface1.AFD_Init();
                //bool amret3 = amface2.AFD_Init();
                //bool amret4 = amface3.AFD_Init();
                faceinitRes = amret1 & amret2;
                errorTime = 0;
                faceErrorNum = 0;
            }catch(Exception e){
                DebugLog(e.StackTrace);
            }
            finally
            {
                facerestarting = false;
            }
            
        }
        private string CapOne(ref int pathIdx, string path, ref bool ret)
        {
            try{
                path = String.Format("{0}/face{1}.jpg", pathautoCapT, pathIdx);
                if (faceinitRes && HkAction.CapturePicture(path, SessionId[0]))
                {
                    ret = true;
                    //Console.WriteLine("拍照中成功。。。");
                }
                else
                {
                    ret = false;
                    //Console.WriteLine("拍照失败。。。");
                }
                if (pathIdx < 6) pathIdx++;
                else pathIdx = 1;
            }catch(Exception e){
                DebugLog("拍照异常:"+e.StackTrace);
            }
            return path;
        }

        private string CapTwo(ref int pathIdx, string path,ref bool ret)
        {
            path = String.Format("{0}/face{1}.jpg", pathautoCapT, pathIdx);
            if (faceinitRes && HkAction.CapturePicture(path, SessionId[1]))
            {
                ret = true;
                //Console.WriteLine("拍照中成功。。。");
            }
            else
            {
                ret = false;
            }
            if (pathIdx < 12) pathIdx++;
            else pathIdx = 6;
            return path;
        }
        #endregion
        #region 人脸比对
        private void CompareFace(int addr, string filename) {
            //SendFaceBusy(addr);
            if (!bm_Dev[addr + ""].FaceComparing && bm_Dev[addr + ""].startTime != 0)
            {
                if (bm_Dev[addr + ""].FaceRes)
                {
                    SendOpen(addr);
                }else
                {
                    SendError(addr);
                    DebugLog("人脸超时");
                    Console.WriteLine("人脸超时");
                }
                return;
            }
            else if (bm_Dev[addr + ""].startTime == 0)
            {
                SetPassConflict(addr);
                bm_Dev[addr + ""].startTime = DateTime.Now.Ticks;
                bm_Dev[addr + ""].FaceComparing = true;
                FacePar fp = new FacePar();
                fp.addr = addr;
                fp.filename = filename;
                ThreadPool.QueueUserWorkItem(CompareThread, fp);
            }            
        }
        private void CompareThread(object pr) {
            FacePar fp = pr as FacePar;
            int addr = fp.addr;
            string filename = fp.filename;
            string[] fs = filename.Split(',');
            AmFaceVerify tmpamFace;
            List<byte[]> OrgFeatures =  new List<byte[]>();
            for(int i =0;i<fs.Length;++i){
                OrgFeatures.Add(DataTrans.strToToHexByte(fs[i]));
            }
            
            List<byte[]> tmpFeature;
            if (addr == 1)
            {
                tmpFeature = featrueList1;
                tmpamFace = amface;
            }
            else {
                tmpFeature = featrueList2;
                tmpamFace = amface1;
            }
            //AmFaceVerify amface = fp.amface;
            int fsIdx = 0;
            int pathIdx1 = 1;
            int pathIdx2 = 6;
            Console.WriteLine("startTime{0}", bm_Dev[addr + ""].startTime);
            string path;
            while (DateTime.Now.Ticks - bm_Dev[addr + ""].startTime < faceOverTime)
            {
                //Console.WriteLine("CompareThread{0}", DateTime.Now.Ticks - startTime < 5000 * 10000);
                try
                {
                //ORGFEATURE:
                //    if (bm_Dev[addr + ""].OrgFeature == null || bm_Dev[addr + ""].OldCardNo != bm_Dev[addr + ""].CardNo)
                //    {
                //        byte[] tmp = null;
                //        try
                //        {
                //            if (!facerestarting)
                //            {
                //                tmp = tmpamFace.detectFace(fs[fsIdx]);
                //            }
                //        }
                //        catch (Exception e)
                //        {
                //            DebugLog(e.Message + e.StackTrace);
                //        }
                //        setState(addr, "face");
                //        if (tmp != null) bm_Dev[addr + ""].OrgFeature = tmp;
                //        bm_Dev[addr + ""].OldCardNo = bm_Dev[addr + ""].CardNo;
                //        if (DateTime.Now.Ticks - bm_Dev[addr + ""].startTime > faceOverTime)
                //        {
                //            Console.WriteLine("加载模板人脸失败", filename);
                //            break;
                //        }
                //        goto ORGFEATURE;
                //    }
                    float score = 0;
                    if(!float.TryParse(FaceScore,out score))score =60;
                    int listLen = tmpFeature.Count;
                    bool ret = false;
                    if(addr==1)
                        path = CapOne(ref pathIdx1, pathautoCapT, ref ret);
                    else
                        path = CapTwo(ref pathIdx2, pathautoCapT, ref ret);
                    updateTxt("拍照" + path+"，结果:"+ret+DateTime.Now.ToString("H:i:s"));
                    if (facerestarting || !ret) continue;
                    byte[] featrue = tmpamFace.detectFace(path);
                    for (int i = 0; i<OrgFeatures.Count; i++)
                    {
                        //if (tmpFeature.Count == 0) break;
                        //byte[] featrue = (byte[])tmpFeature[i];
                        score = tmpamFace.matchFace(OrgFeatures[i], featrue);
                        Console.WriteLine("{0}模板线程：分数{1}", filename, score);
                        if (score*100 > 55 && !bm_Dev[addr + ""].FaceRes)
                        {
                            tmpFeature.Clear();
                            featrue = null;
                            Console.WriteLine("{0}分数高于阈值，比对成功 特征数组1:{1},特征数组2:{2}", filename, featrueList1.Count, featrueList2.Count);
                            bm_Dev[addr + ""].OrgFeature = null;
                            if (!bm_Dev[addr + ""].FaceRes)
                            {
                                bm_Dev[addr + ""].FaceRes = true;
                            }
                            bm_Dev[addr + ""].FaceComparing = false;
                            return;
                        }
                    }
                    bm_Dev[addr + ""].OrgFeature = null;
                    if (fsIdx < fs.Length - 1) fsIdx++;
                    else fsIdx = 0;
                }catch(Exception ex){
                    Console.WriteLine(ex.StackTrace);
                    DebugLog(ex.Message + ex.StackTrace);
                    Thread.Sleep(500);
                }
            }
            bm_Dev[addr + ""].FaceComparing = false;
        }

        #endregion

        #region 初始化串口
        private void InitCom()
        {
            string[] ports = SerialPort.GetPortNames();
            Array.Sort(ports);
            comboBoxPortSelect.Items.AddRange(ports);
            mycomm.ReadTimeout = 32;
            mycomm.BaudRate = 115200;
            if (historycom.Length > 0)
            {
                comboBoxPortSelect.Text = historycom;
                if (FaceModel)
                {
                    btnStart.Enabled = false;
                    InitFace();
                }
                else {
                    Start();
                }
            }
            else
            {
                if (comboBoxPortSelect.Items.Count > 0)
                {
                    comboBoxPortSelect.SelectedIndex = comboBoxPortSelect.Items.Count - 1;
                    if (mycomm.IsOpen) mycomm.Close();
                    //添加事件注册
                    DebugLog("初始化串口");
                    StartComCheckThread();
                }
            }
            //mycomm.DataReceived += comm_DataReceived;
        }
        #endregion

        #region 日志清除
        private void LogClearThread()
        {
            ThreadPool.QueueUserWorkItem(LogClear, "");
        }
        private void LogClear(object state)
        {
            try
            {
                DateTime now = DateTime.Now;
                int year = now.Year;
                int month = now.Month;
                int day = now.Day;
                string Current = AppDomain.CurrentDomain.BaseDirectory;//获取当前根目录
                XmlDocument xml = new XmlDocument();
                xml.Load(Current + "/log4net.config");
                XmlNodeList nodelist = xml.GetElementsByTagName("file");
                string path = nodelist[0].Attributes[0].Value;
                DirectoryInfo theFolder = new DirectoryInfo(@path);
                DirectoryInfo[] dirInfo = theFolder.GetDirectories();
                //遍历文件夹
                foreach (DirectoryInfo theSecFolder in dirInfo)
                {
                    DirectoryInfo[] dirSecInfo = theSecFolder.GetDirectories();
                    //遍历文件夹
                    foreach (DirectoryInfo NextFolder in dirSecInfo)
                    {
                        FileInfo[] fileInfo = NextFolder.GetFiles();
                        foreach (FileInfo NextFile in fileInfo)  //遍历文件
                        {
                            string name = NextFile.Name.Substring(0, 8);
                            string strY = name.Substring(0, 4);
                            string strM = name.Substring(4, 2);
                            string strD = name.Substring(6, 2);
                            int _y = int.Parse(strY);
                            int _m = int.Parse(strM);
                            int _d = int.Parse(strD);
                            if (_y < year || _y == year && _m < month - 2 || (_y == year && _m == month && _d < day - 7))
                            {
                                File.Delete(NextFile.FullName);
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                DebugLog("异常" + e.Message + "/r/n" + e.StackTrace);
            }
        }
        #endregion

        void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            closeForm();
        }
        public void closeForm()
        {
            try
            {
                this.Controls.Clear();
                notifyIcon.Visible = false;
                if (mycomm.IsOpen) mycomm.Close();
                new Thread(new ThreadStart(closeface)).Start();
            }
            catch { }
        }

        private void closeface()
        {
            if (FaceModel)
            {
                DebugLog("关闭人脸引擎");
                iscaptrue = false;
                HkSDK.OpenSDK_FiniLib();
                amface.Uninit();
                amface1.Uninit();
                //amface2.Uninit();
                //amface3.Uninit();
            }
        }

        void mini_MouseLeave(object sender, EventArgs e)
        {
            mini.Image = Properties.Resources.mini;
        }

        void mini_MouseEnter(object sender, EventArgs e)
        {
            mini.Image = Properties.Resources.mini_f;
        }

        void close_MouseLeave(object sender, EventArgs e)
        {
            close.Image = Properties.Resources.close;
        }

        void close_MouseEnter(object sender, EventArgs e)
        {
            close.Image = Properties.Resources.close_f;
        }

        void option_MouseEnter(object sender, EventArgs e)
        {
            option.Image = Properties.Resources.option_f;
        }
        void option_MouseLeave(object sender, EventArgs e)
        {
            option.Image = Properties.Resources.option;
        }
        private void option_Click(object sender, EventArgs e)
        {
            OptionForm optionForm = new OptionForm();
            optionForm.Tag = this;
            optionForm.inaddr = InMachinesDevNo;
            optionForm.outaddr = OutMachinesDevNo;
            optionForm.COM = comboBoxPortSelect.Text;
            optionForm.SerPort = mycomm;
            optionForm.Face = FaceModel;
            optionForm.facePreview = hostPb;
            optionForm.AddrChanged += new EventHandler(
                (sender1, e1) =>
                {
                    DevSetting("addr", sender1);
                }
            );
            optionForm.PswChanged += new EventHandler(
                (sender1, e1) =>
                {
                    DevSetting("psw", sender1);
                }
            );
            optionForm.AllowTmpChanged += new EventHandler(
                (sender1, e1) =>
                {
                    DevSetting("tmp",sender1);
                }
            );
            optionForm.LogStateChanged += new EventHandler(
                (sender1, e1) =>
                {
                    LogFlag = optionForm.LogState;
                }
            );
            optionForm.SendSpaceChanged += new EventHandler(
                (sender1, e1) =>
                {
                    sendspace = optionForm.SendSpace;
                }
            );
            optionForm.ShowDialog();
        }

        private void DevSetting(string tmp,object obj) {
            running = false;
            Thread.Sleep(1000);
            int len = 0;
            switch(tmp){
                case "tmp":
                    RadioButton rb = obj as RadioButton;
                    if (rb.Checked)
                    {
                        for (int i = 0; i < OutMachines.Length; ++i)
                        {
                            byte[] pack = dh.GetPackage(OutMachines[i], "", DataHelper.CMD.CMD_ALLOW, ref len);
                            mycomm.Write(pack, 0, len);
                            Thread.Sleep(200);
                        }
                    }
                    else
                    {
                        for (int i = 0; i < OutMachines.Length; ++i)
                        {
                            byte[] pack = dh.GetPackage(OutMachines[i], "", DataHelper.CMD.CMD_DENY, ref len);
                            mycomm.Write(pack, 0, len);
                            Thread.Sleep(200);
                        }
                    }
                break;
            }
            ComException(true);
            //Start();
            MessageBox.Show("设置成功");
        }

        void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && canMove)
            {
                Point mouseSet = Control.MousePosition;
                mouseSet.Offset(mouseOff.X, mouseOff.Y);  //设置移动后的位置  
                Location = mouseSet;
            }
        }

        void Form1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                canMove = false;
            }
        }

        void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                mouseOff = new Point(-e.X, -e.Y);
                canMove = true;
            }
        }

        void Form1_Resize(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                InTasker(true);
            }
        }
        private void InTasker(bool show)
        {
            if (show)
            {
                this.Hide();
                this.ShowInTaskbar = false;
                this.notifyIcon.Visible = true;
            }
            else
            {
                this.Show();
                this.WindowState = FormWindowState.Normal;
                notifyIcon.Visible = false;
                this.ShowInTaskbar = true;
            }
        }

        private void WriteLog(Exception ex)
        {
            LogHelper.WriteLog(typeof(Exception), "异常：" + ex.Message + "\r\n\t 堆栈：" + ex.StackTrace);
        }

        public static void DebugLog(Object obj)
        {
            if (LogFlag == true)
                LogHelper.WriteLog(typeof(Exception), obj.ToString());
        }

        bool btnStartFocus = false;
        void button1_MouseLeave(object sender, System.EventArgs e)
        {
            if (running)
            {
                if (btnStartFocus) { btnStart.Image = Properties.Resources.stop_f; btnStart.ForeColor = Color.White; }
                else { btnStart.Image = Properties.Resources.stop; btnStart.ForeColor = ForeColor; }
            }
            else
            {
                if (btnStartFocus)
                {
                    btnStart.Image = Properties.Resources.start;
                    btnStart.ForeColor = ForeColor;
                }
                else
                {
                    btnStart.Image = Properties.Resources.start_f;
                    btnStart.ForeColor = Color.White;
                }
            }
        }

        void button1_MouseEnter(object sender, System.EventArgs e)
        {
            if (running)
            {
                btnStart.Image = Properties.Resources.stop_f;
            }
            else
            {
                btnStart.Image = Properties.Resources.start_f;
            }
            btnStart.ForeColor = Color.White;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (comboBoxPortSelect.Text.Length <= 0)
            {
                ToolTip tt = new ToolTip();
                tt.Show("请选择串口", comboBoxPortSelect, 1000);
                return;
            }
            if (button1.Text.Contains("开"))
            {
                if (FaceModel)
                {
                    if (!faceinitRes)
                    {
                        MessageBox.Show("人脸模块初始化失败", "系统异常", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                    if (!Play())
                    {
                        MessageBox.Show("摄像头初始化失败", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    else Start();
                }
            }
            else Start();
            ini.WriteValue("Setting", "com", comboBoxPortSelect.Text);
        }

        private void Start()
        {
            int trynum = 3;
            lblToolStripStatus.Text = "串口状态：正在打开串口...";
        Retry:
            if (!mycomm.IsOpen)
            {
                try
                {
                    ApiService.inSwipeCard("0", "0");
                }
                catch (Exception ex)
                {
                    lblToolStripStatus.Text = "串口状态：断开连接";
                    if (ex.Message.Equals("Begin failed with SQL exception"))
                    {
                        WriteLog(ex);
                        MessageBox.Show("无法连接到数据库，请确认数据库服务是否开启，或检查配置文件" + AppDomain.CurrentDomain.BaseDirectory + "/Config/hibernate.cfg.xml", "系统异常", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    else if (ex.Message.Contains("could not execute query"))
                    {
                        MessageBox.Show("数据库不存在，请检查配置文件" + AppDomain.CurrentDomain.BaseDirectory + "/Config/hibernate.cfg.xml", "系统异常", MessageBoxButtons.OK, MessageBoxIcon.Error);

                    }
                    else
                    {
                        MessageBox.Show(ex.Message, "系统异常", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        WriteLog(ex);
                    }
                    return;
                }
                if (!openCom())
                {
                    if (trynum > 0)
                    {
                        trynum--;
                        lblToolStripStatus.Text = "串口状态：重试...";
                        goto Retry;
                    }
                }
                else
                {
                    iscaptrue = true;
                    if (FaceModel)
                    {
                        //autoCapThread1 = new Thread(new ThreadStart(autoCapT1));
                        //autoCapThread1.Start();
                        //if (SessionId.Count == 2)
                        //{
                        //    autoCapThread2 = new Thread(new ThreadStart(autoCapT2));
                        //    autoCapThread2.Start();
                        //}
                    }
                    btnStart.Image = Properties.Resources.stop_f;
                    btnStart.BackColor = Color.FromArgb(13, 111, 182);
                    btnStart.Text = "停 止（&Q）";
                    runThread();
                }
            }
            else
            {
                DebugLog("关闭串口");
                iscaptrue = false;
                ComException(true);
            }
        }

        private void stopThread()
        {
            running = false;
        }
        private void runThread()
        {
            lblToolStripStatus.Text = "串口状态：正在连接...";
            ThreadPool.SetMaxThreads(20, 50);
            running = true;
            ThreadPool.QueueUserWorkItem(runData, "ocm");
            lblToolStripStatus.Text = "串口状态：正在运行...";
        }

        private void StartComCheckThread()
        {
            comchecking = true;
            CheckForIllegalCrossThreadCalls = false;
            ThreadPool.QueueUserWorkItem(ComCheckThread, "");
        }

        private void StopComCheckThread()
        {
            comchecking = false;
        }

#region 串口检查线程，查看是否有新的串口设备
        private void ComCheckThread(object state)
        {
            lock (CheckLock)
            {
                string[] ports = null;
                ports = SerialPort.GetPortNames();
                while (comchecking)
                {
                    ports = SerialPort.GetPortNames();
                    if (ports.Length > comboBoxPortSelect.Items.Count)
                    {
                        Array.Sort(ports);
                        comboBoxPortSelect.Items.Clear();
                        comboBoxPortSelect.Items.AddRange(ports);
                        StopComCheckThread();
                    }
                    Thread.Sleep(1500);
                }
            }
        }
#endregion
        private void runData(object state)
        {
            Dictionary<int, byte[]> package = new Dictionary<int, byte[]>();
            devResult = new byte[TOTALNUM];
            int recvNum = 0;
            mycomm.Parity = Parity.Mark;
            DelaySw.Start();   //接受计时器
            BrackeMachine tmpMachine = null;
            for (int devidx = 0, len = UseMachines.Length; devidx < len; ++devidx)
            {
                BrackeMachine tmpDev = bm_Dev["" + UseMachines[devidx]];
                SendError_NoConflict(tmpDev.DevNo);
                Thread.Sleep(200);
            }
            int[] devarr = { 0, 0, 0, 0, 0, 0, 0, 0 };
            System.Text.StringBuilder errorSt = new System.Text.StringBuilder();
            int runnum = 0;
            while (running)
            {
                DebugLog("询问中");
                if(FaceModel){
                    //if (autoCapThread1.ThreadState.ToString().Equals("Stopped")&&!facerestarting) {
                    //    DebugLog("拍照线程终止，重新启动");
                    //    updateTxt("拍照线程终止，重新启动");
                    //    autoCapThread1 = new Thread(new ThreadStart(autoCapT1));
                    //    autoCapThread1.Start();
                    //}

                    //if (autoCapThread2.ThreadState.ToString().Equals("Stopped") && !facerestarting && SessionId.Count == 2)
                    //{
                    //    updateTxt("拍照线程终止，重新启动");
                    //    autoCapThread2 = new Thread(new ThreadStart(autoCapT2));
                    //    autoCapThread2.Start();
                    //}
                }
                for (int devidx = 0, len = UseMachines.Length; devidx < len; ++devidx)
                {
                    recvNum = 0;
                    try
                    {
                        tmpMachine = bm_Dev[UseMachines[devidx] + ""];
                        mycomm.Write(tmpMachine.Package, 0, packlen);//串口写
                        DebugLog((devidx + 1) + "设备串口");
                        DelaySw.Restart();
                        do
                        {
                            int n = mycomm.BytesToRead;
                            if (n > 0)
                            {
                                recvNum += mycomm.Read(devResult, recvNum, n > 31 ? 31 : n);//串口读
                            }

                        } while (recvNum != 11 && recvNum != 31 && DelaySw.ElapsedMilliseconds < 30 + sendspace);

                    }
                    catch (Exception e)
                    {
                        ComException(false);
                        WriteLog(e);
                        Console.WriteLine(e.Message + e.StackTrace);
                        return;
                        //串口突然关闭
                    }
                    if (devResult[0] != 0)
                    {
                        dealData(devResult);
                        resetData();
                    }
                    else
                    {
                        devarr[devidx] += 1;
                        setState(devidx + 1, "off");
                    }

                }
                runnum++;
                if (runnum % 1000 == 0)
                {
                    errorSt.Clear();
                    for (int i = 0; i < devarr.Length; ++i)
                    {
                        errorSt.Append((i + 1) + "的错误数:" + devarr[i] + "，");
                    }
                    updateTxt("错误统计" + errorSt.ToString());
                    DebugLog("错误统计" + errorSt.ToString());
                }
            }
            updateTxt("询问结束");
        }

        private void setState(int addr, string state)
        {
            try
            {
                StateBox sbox = stateList[addr + ""];
                switch (state.ToLower())
                {
                    case "busy":
                        sbox.BackColor = StateBusy;
                        break;
                    case "error":
                        sbox.BackColor = StateError;
                        break;
                    case "off":
                        sbox.BackColor = StateOff;
                        break;
                    case "sql":
                        sbox.BackColor = StateSql;
                        break;
                    case "wait":
                        sbox.BackColor = StateWait;
                        break;
                    case "face":
                        sbox.BackColor = StateFace;break;
                    default:
                        sbox.BackColor = StateOn;
                        break;
                }
            }
            catch { }
            //stateList[addr+""].addr = addr.ToString();
        }

        private void ComException(bool manualclose)
        {
            if (System.DateTime.Now.Ticks - CLoseTime < closespace) return;
            CLoseTime = System.DateTime.Now.Ticks;
            stopThread();
            closeCom();
            lblToolStripStatus.Text = "串口状态：断开连接";
            btnStart.Image = Properties.Resources.start_f;
            btnStart.BackColor = HeaderBack;
            btnStart.Text = "开 始（&Q）";
            comboBoxPortSelect.Enabled = true;
            ResetState();
            if (!manualclose)
            {
                DebugLog("串口异常 设备重连");
                Start();
                //MessageBox.Show("设备连接断开", "系统异常", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void ResetState()
        {
            foreach (KeyValuePair<string, StateBox> state in stateList)
            {
                state.Value.BackColor = StateOff;
            }
        }

        private void updateTxt(string txt)
        {
            //return;
            Console.WriteLine(txt);
        }
        //设置冲突设备号
        private void SetPassConflict(int addr)
        {
            lock (SetConflictLock)
            {
                for (int i = 0, len = InMachines.Length; i < len; ++i)
                {
                    if (addr == InMachines[i])
                    {
                        BusyMachine[i] = OutMachines[i];
                    }
                    else if (addr == OutMachines[i]) BusyMachine[i] = InMachines[i];
                }
                ResetStopWatch(addr);
            }
        }

        private void ResetStopWatch(int addr)
        {
            for (int i = 0, len = BusyMachine.Length; i < len; ++i)
            {
                if (addr == BusyMachine[i]) lockswlist[i].Restart();//每置锁一次 就对响应锁重新计数
            }
        }

        private bool IsPassConflict(int addr)
        {
            for (int i = 0, len = BusyMachine.Length; i < len; ++i)
            {
                if (addr == BusyMachine[i])
                {
                    updateTxt("冲突检测:" + addr + "有冲突");
                    return true;
                }
            }
            return false;
        }

        //清除冲突线程
        private void ClearPassConflict(int addr, int delay)
        {
            PAR par = new PAR();
            par.addr = addr;
            par.delay = delay;
            ThreadPool.QueueUserWorkItem(ClearPassConflictThread, par);
        }
        private void ClearPassConflictThread(object state)
        {
            lock (ClearConflictLock)
            {
                try
                {
                    PAR par = (PAR)state;
                    int addr = par.addr;
                    int delay = par.delay;
                    for (int i = 0, len = BusyMachine.Length; i < len; ++i)
                    {
                        if (addr == InMachines[i] || addr == OutMachines[i])
                        {
                            if (lockswlist[i].ElapsedMilliseconds == 0) lockswlist[i].Start();
                            //else if (lockswlist[i].ElapsedMilliseconds >= delay) lockswlist[i].Restart();
                            while (lockswlist[i].ElapsedMilliseconds < delay) { };
                            BusyMachine[i] = -1;
                            updateTxt(addr + ".清除冲突" + BusyMachine[i]);
                            break;
                        }
                    }
                }
                catch (Exception e)
                {
                    //MessageBox.Show(e.Message);
                    Console.WriteLine(e.Message + e.StackTrace);
                }
            }
        }

        private void dealData(object dt)
        {
            byte[] data = (byte[])dt;
            if (!dh.ValidSum(data))
            {
                updateTxt("校验失败");
                return;
            }
            byte[] ack = dh.GetACK(data);
            int addr = dh.GetAddr(data);
            if (addr <= 0) return;
            BrackeMachine tmpbm = new BrackeMachine();
            try
            {
                tmpbm = bm_Dev[addr + ""];
            }
            catch (Exception ex)
            {
                setState(addr, "off");
                DebugLog("异常：" + ex.Message + "\r\n\t 堆栈：" + ex.StackTrace);
                return;
            }
            Dictionary<string, object> swipe = null;
            DebugLog(addr + "收到下位机应答");
            if (dh.EqAck(ack, DataHelper.ACK.ACK_CARD))
            {
                updateTxt(addr + "收到应答：读卡");

                DebugLog(addr + "收到应答：读卡");
                if (IsPassConflict(bm_Dev[addr + ""].DevNo))//冲突判断
                {
                    //if (!bm_Dev[addr+""].CFErrorFlag)
                    //{
                    updateTxt(addr + "读卡时冲突");
                    SendError_NoConflict(bm_Dev[addr + ""].DevNo);
                    bm_Dev[addr + ""].CFErrorFlag = true;
                    //}
                    return;
                }

                string cardno = dh.GetData(data);
                if (cardno == null || cardno.Length <= 0)
                {
                    DebugLog(addr + "重新请求卡号");
                    updateTxt(addr + "--发送请求：指纹 卡号：" + cardno);
                    RequsetCardno(addr);
                    return;
                }
                else 
                {
                    if (bm_Dev[addr + ""].CardNo == cardno && bm_Dev[addr + ""].IsDecable())
                    {
                        updateTxt("重试");
                        bm_Dev[addr + ""].DecTry();

                    }
                    else
                    {
                        DebugLog(addr + "判断是否开门:" + cardno);
                        if (bm_Dev[addr + ""].state == 1)
                        {
                            if (cardno != bm_Dev[addr + ""].CardNo)
                            {
                                ResetSwipe(addr);
                                DealCard(addr, cardno);
                            }
                        }
                        else
                        {
                            DealCard(addr, cardno);
                        }
                    }
                }
            }
            else if (dh.EqAck(ack, DataHelper.ACK.ACK_FINGER))
            {
                updateTxt(addr + "收到应答：指纹");
                string cardno = bm_Dev[addr + ""].CardNo;
                if (cardno == null || cardno.Length <= 0)
                {
                    RequsetCardno(addr);
                    return;
                }
                DebugLog(addr + "收到应答：指纹 " + cardno);
                if (IsPassConflict(bm_Dev[addr + ""].DevNo))//冲突判断
                {
                    //if (!bm_Dev[addr+""].CFErrorFlag)
                    //{
                    updateTxt(addr + "指纹时冲突");
                    SendError_NoConflict(bm_Dev[addr + ""].DevNo);
                    bm_Dev[addr + ""].CFErrorFlag = true;
                    //}
                    return;
                }
                if (IsInMachines(addr))
                {
                    //runInSwipe(addr);//注释后为开启线程请求数据
                    /************进闸机************/
                    if (bm_Dev[addr + ""].InSwipe == null)
                    {
                        DebugLog(addr + "查询结果为空");
                        SwipeThread(addr, true);
                        return;
                    }
                    else swipe = bm_Dev[addr + ""].InSwipe;
                    if ((bool)swipe["is_open"])
                    {
                        DebugLog(addr + "不用验证指纹" + bm_Dev[addr + ""].CardNo);
                        SendOpen(addr);
                    }
                    else
                    {
                        if ((bool)swipe["flag"])
                        {
                            bm_Dev[addr + ""].Valid = true;
                            if (FaceModel)
                            {
                                string varify_type = swipe["varify_type"].ToString();
                                if (varify_type.Equals("2"))
                                {
                                    DebugLog(addr + "需要验证人脸" + bm_Dev[addr + ""].CardNo);
                                    CompareFace(addr, swipe["data"].ToString());
                                    updateTxt(bm_Dev[addr + ""].CardNo + "设备" + addr + "需要验证人脸");
                                }
                                else
                                {
                                    DebugLog(addr + "需要验证指纹" + bm_Dev[addr + ""].CardNo);
                                    SendFinger(addr, swipe["data"].ToString());
                                    updateTxt(bm_Dev[addr + ""].CardNo + "设备" + addr + "需要验证指纹");
                                }
                            }
                            else
                            {
                                DebugLog(addr + "需要验证指纹" + bm_Dev[addr + ""].CardNo);
                                SendFinger(addr, swipe["data"].ToString());
                                updateTxt(bm_Dev[addr + ""].CardNo + "设备" + addr + "需要验证指纹");
                            }
                        }
                        else
                        {
                            SendError(addr);
                        }
                    }
                }
                else
                {
                    //runOutSwipe(addr);//注释后为开启线程请求数据
                    /************出闸机************/
                    if (bm_Dev[addr + ""].OutSwipe == null)
                    {
                        DebugLog(addr + "查询结果为空");
                        SwipeThread(addr, false);
                        return;
                    }
                    else swipe = bm_Dev[addr + ""].OutSwipe;
                    if ((bool)swipe["is_open"])
                        SendOpen(addr);
                    else
                        SendError(addr);
                }
            }
            else if (dh.EqAck(ack, DataHelper.ACK.ACK_WATING))
            {
                setState(addr, "wait");
                bm_Dev[addr + ""].Busing = true;
                bm_Dev[addr + ""].state = 1;
                SetPassConflict(addr);
                DebugLog(addr + "等待比对" + bm_Dev[addr + ""].CardNo);
                updateTxt(addr + "收到应答：等待比对 忙碌中..." + bm_Dev[addr + ""].CardNo);
            }
            else if (dh.EqAck(ack, DataHelper.ACK.ACK_SUCCESS))
            {
                //updateTxt(addr + "收到应答：比对成功");
                //DebugLog(addr + "比对成功" + bm_Dev[addr+""].CardNo);
                //string cardno = bm_Dev[addr+""].CardNo;
                //if (cardno==null||cardno.Length <= 0)
                //{
                //    RequsetCardno(addr); 
                //    return;
                //}
                try
                {
                    SendOpen(addr);
                    //FingerThread(addr, true);
                }
                catch (Exception e)
                {

                    Console.WriteLine(e.Message + e.StackTrace);
                    //MessageBox.Show("发生错误：" + e.Message + "\r\n" + "详情：" + e.StackTrace);
                    //ComException(false);
                }
            }
            else if (dh.EqAck(ack, DataHelper.ACK.ACK_FAIL))
            {
                updateTxt(addr + "收到应答：比对失败");
                DebugLog(addr + "比对失败" + bm_Dev[addr + ""].CardNo);
                try
                {
                    //FingerThread(addr, false);
                    SendError(addr);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message + e.StackTrace);
                }
            }
            else if (dh.EqAck(ack, DataHelper.ACK.ACK_EMPTY))
            {
                DebugLog(addr + "收到应答 EMPTY");
                setState(addr, "on");
                if (bm_Dev[addr + ""].state == 3)
                {
                    if (bm_Dev[addr + ""].Valid) {
                        FingerThread(addr, true);
                    }
                    //开闸机
                    ClearPassConflict(addr, 3000);
                    ContinuSendError(addr);
                    ResetSwipe(addr);
                }
                else if (bm_Dev[addr + ""].state == 2)
                {
                    if (bm_Dev[addr + ""].Valid)
                    {
                        FingerThread(addr, false);
                    }
                    bm_Dev[addr + ""].FaceCompareOver();
                    //异常
                    ClearPassConflict(addr, 1000);
                    ResetSwipe(addr);
                }
                else if (bm_Dev[addr + ""].state == 1)
                {
                    //等待比对
                    ClearPassConflict(addr, 100);
                    bm_Dev[addr + ""].state = 0;
                    ResetSwipe(addr);
                }
            }
            else
            {
                setState(addr, "off");
            }
            Thread.Sleep(10);

        }

        #region 卡数据相关处理
        //清除同一张卡 连续同放向刷异常
        private void ContinuSendError(int addr)
        {
            foreach (KeyValuePair<string, BrackeMachine> c in bm_Dev)
            {
                if (bm_Dev[addr + ""].CardNo == c.Value.CardNo &&
                        bm_Dev[addr + ""].DevNo != c.Value.DevNo &&
                        bm_Dev[addr + ""].CardNo != "" &&
                        IsSameDirect(bm_Dev[addr + ""].DevNo, c.Value.DevNo))
                //bm_Dev[addr+""].Direct!= bm_Dev[i].Direct) 
                {
                    SendError(c.Value.DevNo);
                    DebugLog("开门地址:" + addr + ",接受错误指令地址:" + c.Value.DevNo);
                    break;
                }
            }
        }

        private bool IsInMachines(int addr)
        {
            for (int i = 0, len = InMachines.Length; i < len; ++i)
            {
                if (addr == InMachines[i]) return true;
            }
            return false;
        }

        private bool IsSameDirect(int addr1, int addr2)
        {
            bool addr1Flag, addr2Flag;
            addr1Flag = addr2Flag = false;
            for (int i = 0, len = InMachines.Length; i < len; ++i)
            {
                if (addr1 == InMachines[i]) addr1Flag = true;
                if (addr2 == InMachines[i]) addr2Flag = true;
            }
            if (addr1Flag && addr2Flag) return true;
            else return false;
        }

        private void DealCard(int addr, string cardno)
        {
            bm_Dev[addr + ""].CardNo = cardno;
            bm_Dev[addr + ""].NewTry();
            bm_Dev[addr + ""].state = 0;
            if (IsInMachines(addr)) SwipeThread(addr, true);
            else SwipeThread(addr, false);
        }

        private void ResetSwipe(int addr)
        {
            bm_Dev[addr + ""].Valid = false;
            bm_Dev[addr + ""].startTime = 0;
            bm_Dev[addr + ""].FaceCompareOver();
            bm_Dev[addr + ""].state = 0;//初始化
            bm_Dev[addr + ""].CardNo = "";
            bm_Dev[addr + ""].DbingOut = bm_Dev[addr + ""].DbingIn = bm_Dev[addr + ""].Dbing = false;
            updateTxt(addr + "重置数据");
            bm_Dev[addr + ""].InSwipe = null;
            bm_Dev[addr + ""].OutSwipe = null;
        }
        #endregion

        #region 请求指纹线程
        private void SwipeThread(object dt, bool isIn)
        {
            if (isIn) ThreadPool.QueueUserWorkItem(runInSwipe, dt);
            else ThreadPool.QueueUserWorkItem(runOutSwipe, dt);
        }
        #endregion

        #region 数据库进门请求
        private void runInSwipe(object dt)
        {
            int addr = (int)dt;
            lock (InSwiperLock)
            {
                if (bm_Dev[addr + ""].DbingIn) return;
                bm_Dev[addr + ""].DbingIn = true;
                try
                {
                    DebugLog(addr + "进场 请求数据库 开始" + bm_Dev[addr + ""].CardNo + "FaceModel:" + FaceModel);
                    if (bm_Dev[addr + ""].InSwipe != null) return;
                        bm_Dev[addr + ""].InSwipe = ApiService.inSwipeCard(bm_Dev[addr + ""].CardNo, dt.ToString());
                    DebugLog(addr + "进场 请求数据库 完成" + bm_Dev[addr + ""].CardNo);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message + e.StackTrace);
                    DebugLog(e.Message + e.StackTrace);
                    setState(addr, "sql");
                    //MessageBox.Show("发生错误：" + e.Message + "\r\n" + "详情：" + e.StackTrace);
                    //ComException(false);
                }
                bm_Dev[addr + ""].DbingIn = false;
            }
        }
        #endregion

        #region 数据库出门请求
        private void runOutSwipe(object dt)
        {
            int addr = (int)dt;
            lock (OutSwiperLock)
            {
                if (bm_Dev[addr + ""].DbingOut) return;
                bm_Dev[addr + ""].DbingOut = true;
                try
                {
                    DebugLog(addr + "出场 请求数据库 开始" + bm_Dev[addr + ""].CardNo);
                    if (bm_Dev[addr + ""].OutSwipe != null) return;
                    bm_Dev[addr + ""].OutSwipe = ApiService.outSwipeCard(bm_Dev[addr + ""].CardNo, dt.ToString());
                    DebugLog(addr + "出场 请求数据库 完成" + bm_Dev[addr + ""].CardNo);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message + e.StackTrace);
                    DebugLog(e.Message + e.StackTrace);
                    setState(addr, "sql");
                    //MessageBox.Show("发生错误：" + e.Message + "\r\n" + "详情：" + e.StackTrace);
                }
                bm_Dev[addr + ""].DbingOut = false;
            }
        }
        #endregion

        #region 请求指纹数据
        private void FingerThread(object dt, bool result)
        {
            int addr = (int)dt;
            if (!bm_Dev[addr + ""].Dbing)
            {
                bm_Dev[addr + ""].Dbing = true;
                try
                {
                    if (bm_Dev[addr + ""].CardNo != null && bm_Dev[addr + ""].CardNo != "")
                        ApiService.swipeFingerPrintResult(bm_Dev[addr + ""].CardNo, result, addr.ToString());
                    //bm_Dev[addr+""].CardNo = ""; 
                }
                catch(Exception e){
                    DebugLog(e.Message + e.StackTrace);
                }
                bm_Dev[addr + ""].Dbing = false;
            }
        }
        #endregion

        #region 发送请求卡号指令
        private void RequsetCardno(int addr)
        {
            try
            {
                int len = 0;
                byte[] pack = dh.GetPackage(addr, "", DataHelper.CMD.CMD_CARD, ref len);
                mycomm.Write(pack, 0, len);
                //Thread.Sleep(30);
                updateTxt(addr + "--发送请求：卡号");
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message + e.StackTrace);
                //MessageBox.Show("发生错误：" + e.Message + "\r\n" + "详情：" + e.StackTrace);
            }
        }
        #endregion

        #region 发送开门指令
        private void SendOpen(int addr)
        {
            try
            {
                int len = 0;
                SetPassConflict(addr);
                byte[] pack = dh.GetPackage(addr, "", DataHelper.CMD.CMD_OPEN, ref len);
                mycomm.Write(pack, 0, len);
                Thread.Sleep(30);
                if (IsInMachines(addr))
                {
                    DebugLog(addr + "进闸机 发送命令：直接开门" + bm_Dev[addr + ""].CardNo);
                    updateTxt(addr + "--进场----发送命令：直接开门" + bm_Dev[addr + ""].CardNo);
                    bm_Dev[addr + ""].Direct = "in";
                }
                else
                {
                    DebugLog(addr + "出闸机 发送命令：直接开门" + bm_Dev[addr + ""].CardNo);
                    updateTxt(addr + "--出场----发送命令：直接开门" + bm_Dev[addr + ""].CardNo);
                    bm_Dev[addr + ""].Direct = "out";
                }
                bm_Dev[addr + ""].FaceComparing = false;
                bm_Dev[addr + ""].FaceRes = false;
                bm_Dev[addr + ""].state = 3;
                bm_Dev[addr + ""].Busing = false;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message + e.StackTrace);
                //MessageBox.Show("发生错误：" + e.Message + "\r\n" + "详情：" + e.StackTrace);
            }
        }
        #endregion

        #region 发送错误
        private void SendError(int addr)
        {
            try
            {
                setState(addr, "error");
                int len = 0;
                byte[] pack = dh.GetPackage(addr, "", DataHelper.CMD.CMD_ERROR, ref len);
                mycomm.Write(pack, 0, len);
                Thread.Sleep(40);
                updateTxt(addr + "--发送请求：异常");
                bm_Dev[addr + ""].state = 2;
                bm_Dev[addr + ""].Busing = false; 
                bm_Dev[addr + ""].FaceComparing = false;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message + e.StackTrace);
                //MessageBox.Show("发生错误：" + e.Message + "\r\n" + "详情：" + e.StackTrace);
            }
        }
        #endregion

        #region 发送端延时冲错误
        private void SendError_NoConflict(int addr)
        {
                try
                {
                    updateTxt("发送冲突错误" + addr);
                    int len = 0;
                    byte[] pack = dh.GetPackage(addr, "", DataHelper.CMD.CMD_ERROR, ref len);
                    mycomm.Write(pack, 0, len);
                    Thread.Sleep(20);
                    bm_Dev[addr + ""].state = 0;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message + e.StackTrace);
                    //MessageBox.Show("发生错误：" + e.Message + "\r\n" + "详情：" + e.StackTrace);
                }
        }
        #endregion

        private void SendFaceBusy(int addr) {
            try { 
                
                bm_Dev[addr + ""].Busing = true;
                int len = 0;
                byte[] pack = dh.GetPackage(addr, "", DataHelper.CMD.CMD_FACE, ref len);
                mycomm.Write(pack, 0, len);
                bm_Dev[addr + ""].Busing = false;
                Thread.Sleep(30);
                DebugLog(addr + "发送人脸忙碌 完成" + bm_Dev[addr + ""].CardNo);
            }catch(Exception e){
                DebugLog(e.Message + e.StackTrace);
                Console.WriteLine(e.Message + e.StackTrace);
            }
        }

        #region 发送指纹
        private void SendFinger(int addr, string data)
        {
            Stopwatch st = new Stopwatch();
            st.Start();
            try
            {
                bm_Dev[addr + ""].Busing = true;
                setState(addr, "busy");
                DebugLog(addr + "开始发送指纹数据" + bm_Dev[addr + ""].CardNo + ",指纹" + data);
                //SetPassConflict(addr);
                int len = 0;
                byte[] pack = dh.GetPackage(addr, data, DataHelper.CMD.CMD_FINGER, ref len);
                mycomm.Write(pack, 0, len);
                bm_Dev[addr + ""].Busing = false;
                Thread.Sleep(30);
                DebugLog(addr + "发送指纹数据 完成" + bm_Dev[addr + ""].CardNo);
                //ClearPassConflict(addr, 3000);
                updateTxt(addr + "--发送请求：发送指纹数据");
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message + e.StackTrace);
                //MessageBox.Show("发生错误：" + e.Message + "\r\n" + "详情：" + e.StackTrace);
            }
            st.Stop();
        }
        #endregion
        private void resetData()
        {
            devResult = new byte[TOTALNUM];
        }

        private bool openCom()
        {
            try
            {
                mycomm.PortName = comboBoxPortSelect.Text;
                mycomm.Open();
                comboBoxPortSelect.Enabled = false;
                StopComCheckThread();
            }
            catch
            {
                lblToolStripStatus.Text = "串口状态：打开失败！";
                StartComCheckThread();
                return false;
            }
            return true;
        }
        private void closeCom()
        {
            if (mycomm.IsOpen)
            {
                mycomm.DiscardInBuffer();
                mycomm.DiscardOutBuffer();
                mycomm.Close();
            }
            StartComCheckThread();
        }

        private void comboBoxPortSelect_SelectedIndexChanged(object sender, EventArgs e)
        {
            mycomm.Close();
            mycomm.PortName = comboBoxPortSelect.Text;
        }

        void notifyIcon_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                InTasker(false);
            }
            else if (e.Button == MouseButtons.Right)
            {
                IconMenu.Show();
            }
        }

        private void IconMenu_exit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void IconMenu_show_Click(object sender, EventArgs e)
        {
            InTasker(false);
        }

        private void close_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void mini_Click(object sender, EventArgs e)
        {
            this.notifyIcon.ShowBalloonTip(500, "OCM", "正在运行", ToolTipIcon.Info);
            this.WindowState = FormWindowState.Minimized;
        }

        #region 添加手动开门按钮
        private void addManualBox(int addr,bool isIn) {
            ManualBox button = new ManualBox();
            string btnText ;
            Point location;
            int _index = ManualBoxList.Count;
            try{
                btnText = DoorList[_index];
            }catch{
                btnText = addr.ToString();
            }
            int x = _index;
            if (_index % 2 != 0)
            {
                x = _index - 1;
            }
            if(isIn){
                location = new Point(51+x*35, 17);
            }else{
                location = new Point(51 + x * 35, 53);
            }
            button.BackColor = System.Drawing.Color.FromArgb(255, 255, 255);
            button.FlatAppearance.BorderSize = 1;
            button.FlatStyle = System.Windows.Forms.FlatStyle.System;
            button.ForeColor = Color.FromArgb(50,50,50);
            button.Location = location;
            button.Name = "Manual" + addr;
            button.Size = new System.Drawing.Size(63, 34);
            button.Addr = addr;
            button.Index = _index;
            button.Text = btnText;
            button.UseVisualStyleBackColor = false;
            button.Cursor = Cursors.Hand;
            button.Click += new System.EventHandler(this.Manual_Click);

            TextBox tb = new TextBox();
            tb.Location = location;
            tb.Size = button.Size;
            tb.Text = btnText;
            tb.Visible = false;
            tb.MaxLength = 10;
            tb.Multiline = true;
            groupManual.Controls.Add(button);
            groupManual.Controls.Add(tb);
            ManualTextList.Add(tb);
            ManualBoxList.Add(button);
        }
        private void Manual_Click(object sender, EventArgs e)
        {
            ManualBox btn = sender as ManualBox;
            int addr = btn.Addr;
            if (!bm_Dev[addr.ToString()].Busing)
            {
                SendOpen(addr);
                cuStateBox = null;
            }
        }
        #endregion


        #region 修改手动开门按钮别名
        private void ShowManualName() {
            string tmp = "";
            if (!EditName)
            {
                for (int i = 0; i < ManualBoxList.Count; ++i)
                {
                    ManualBoxList[i].Visible = false;
                    ManualTextList[i].Visible = true;
                }

                btnCancel.Visible = true;
                btnRename.Text = "确 定";
                btnRename.Size = new Size(63, 37);
                EditName =true;
            }
            else {
                if (DialogResult.Yes == MessageBox.Show("确定要修改吗？", "", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
                {

                    for (int i = 0; i < ManualBoxList.Count; ++i)
                    {
                        if (ManualTextList[i].Text.Length == 0)
                        {
                            tip.Show("不能为空", ManualTextList[i], 1000);
                            return;
                        }
                    }
                    for (int i = 0; i < ManualBoxList.Count; ++i)
                    {
                        tmp += "," + ManualTextList[i].Text;
                        ManualBoxList[i].Text = ManualTextList[i].Text;
                        ManualBoxList[i].Visible = true;
                        ManualTextList[i].Visible = false;
                    }
                    tmp = tmp.Substring(1);
                    ini.WriteValue("Setting", "doorname", tmp);

                    btnCancel.Visible = false;
                    btnRename.Text = "修改名称";
                    btnRename.Size = new Size(63 , 74);
                    EditName =false;
                }   
            }
        }
        private void btnRename_Click(object sender, EventArgs e)
        {
            ShowManualName();
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < ManualBoxList.Count; ++i)
            {
                ManualBoxList[i].Visible = true;
                ManualTextList[i].Visible = false;
            }
            btnRename.Text = "修改名称";
            btnRename.Size = new Size(63, 74);
            btnCancel.Visible = false;
            EditName = false;
        }
        #endregion

        #region 构造实体类
        public class json
        {
            public int resultCode { get; set; }
            public int count { get; set; }
            public List<cameraList> carameList { get; set; }
        }

        public class cameraList
        {
            public string cameraId { get; set; }
            public string cameraName { get; set; }
            public int cameraNo { get; set; }
            public int defence { get; set; }
            public string deviceId { get; set; }
            public string deviceName { get; set; }
            public int deviceSerial { get; set; }
            public int isEncrypt { get; set; }
            public int isShared { get; set; }
            public string picUrl { get; set; }
            public int status { get; set; }
            public int videoLevel { get; set; }
        }

        public class frm//窗体实体类，用来保存全局变量，并在静态方法中调用
        {
            public int a { get; set; }//记录用户点击的是第几个摄像头
            public int b { get; set; }//记录用户是否正在播放状态，0为未播放，1为正在播放
            public int c { get; set; }//表示用户选择的是几个窗口播放，默认为1

            public string jsonstr { get; set; }//摄像头列表json
            public string cameraid { get; set; }//摄像头id        
            public string safeKey { get; set; }//摄像头密码，默认ABCDEF       

        }

        public static Newtonsoft.Json.Linq.JObject jObjInfo { get; set; }
        public static int isOpertion { get; set; }//0未执行   1正在执行  2已经执行
        public static MessageType mType { get; set; }

        public enum MessageType
        {
            INS_PLAY_EXCEPTION = 0,   // 播放异常，通常是设备断线或网络异常造成
            INS_PLAY_RECONNECT = 1,   // 重连，实时流播放时内部会自动重连
            INS_PLAY_RECONNECT_EXCEPTION = 2,   // 重连异常
            INS_PLAY_START = 3,   // 播放开始
            INS_PLAY_STOP = 4,   // 播放终止
            INS_PLAY_ARCHIVE_END = 5,   // 播放结束，回放结束时会有此消息

            INS_RECORD_FILE = 20,  // 查询的录像文件(录像搜索结果)
            INS_RECORD_SEARCH_END = 21,  // 录像查询结束（暂不使用）
            INS_RECORD_SEARCH_FAILED = 22,  // 录像查询失败
        }

        #endregion

        private void button1_Click_1(object sender, EventArgs e)
        {
            restartAFD();
        }


    }
}
